﻿using System.Data;
using System.Collections;
using Microsoft.VisualBasic;
using System.Diagnostics;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Text;

namespace DAO
{
    public class Encrypt
    {
        
        // This routine creates a new symmetric algorithm object of the chosen type.
        public Encrypt(string strCryptoName)
        {
            // The shared Create method of the abstract symmetric algorithm base class
            // implements a factory design for the creation of its concrete classes.
            crpSym = SymmetricAlgorithm.Create(strCryptoName);
            // Initialize the byte arrays to the proper length for the
            // instantiated crypto class.
            ReDimByteArrays();
        }

        public Encrypt()
        {
        }


        private byte[] abytIV;
        private byte[] abytKey;
        private byte[] abytSalt;
        private SymmetricAlgorithm crpSym;
        private string strPassword = "";
        private string strSaltIVFile = "";

        public string Password
        {
            get
            {
                return strPassword;
            }
            set
            {
                strPassword = value;
            }
        }

        public string SaltIVFile
        {
            get
            {
                return strSaltIVFile;
            }
            set
            {
                if (File.Exists(value))
                {
                    strSaltIVFile = value;
                }
                else
                {
                    throw (new FileNotFoundException("Không tìm thấy file data.dat"));
                }
            }
        }

        // This routine decrypts a file.
        protected internal string DecryptString(string strCipherText, string strEncPass)
        {

            // If the password is an empty string assume the user has not checked the
            // "Advanced" CheckBox or has not entered a password and thus is not using
            // a password-derived key. In such a case the symmetric algorithm object
            // will just use its default values.
            if (strPassword != "")
            {
                OpenSaltIVFileAndSetKeyIV();
            }

            UnicodeEncoding uEncode = new UnicodeEncoding();
            ASCIIEncoding aEncode = new ASCIIEncoding();
            byte[] bytCipherText = Convert.FromBase64String(strCipherText);
            MemoryStream stmPlainText = new MemoryStream();
            MemoryStream stmCipherText = new MemoryStream(bytCipherText);

            // Read in the encrypted file and decrypt.
            CryptoStream csDecrypted = new CryptoStream(stmCipherText, crpSym.CreateDecryptor(), CryptoStreamMode.Read);
            // Create a StreamWriter to write to the temp file.
            StreamWriter swWriter = new StreamWriter(stmPlainText);
            // Read the decrypted stream into a StreamReader.
            StreamReader srReader = new StreamReader(csDecrypted);

            try
            {
                // Write out the decrypted stream.
                swWriter.Write(srReader.ReadToEnd());
            }
            catch (CryptographicException)
            {
                throw (new CryptographicException());
            }
            finally
            {
                // Close and clean up.
                swWriter.Close();
                csDecrypted.Close();
            }
            return uEncode.GetString(stmPlainText.ToArray());
            //SwapFiles(True)
        }

        // This routine encrypts a file.
        protected internal string EncryptString(string strPlainText, string strEncPass)
        {

            // If the password is an empty string assume the user has not checked the
            // "Advanced" CheckBox and thus is not using a password-derived key. In such
            // a case the symmetric algorithm object will just its default values.
            if (strPassword != "")
            {
                OpenSaltIVFileAndSetKeyIV();
            }

            // Create a FileStream object to read in the source file.
            //Dim fsInput As New FileStream(strSourceFile, FileMode.Open, FileAccess.Read)

            // Create a byte array from the FileStream object by reading in the
            // source file.
            UnicodeEncoding uEncode = new UnicodeEncoding();
            ASCIIEncoding aEncode = new ASCIIEncoding();
            //Store plaintext as a byte array
            byte[] abytInput = uEncode.GetBytes(strPlainText);
            //Create a memory stream for holding encrypted text
            MemoryStream stmCipherText = new MemoryStream();

            // Create a FileStream object to write to a temp file.
            //Dim fsCipherText As New FileStream("temp.dat", FileMode.Create, FileAccess.Write)
            //fsCipherText.SetLength(0)

            // Create a Crypto Stream that transforms the file stream using the chosen
            // encryption and writes it to the output FileStream object.
            CryptoStream csEncrypted = new CryptoStream(stmCipherText, crpSym.CreateEncryptor(), CryptoStreamMode.Write);

            // Pass in the unencrypted source file byte array and write out
            // the encrypted bytes to the temp.dat file. Thus, the logic flow is:
            // abytInput ----> Encryption ----> fsCipherText.
            csEncrypted.Write(abytInput, 0, abytInput.Length);

            // When the bytes are all written it's important to indicate to the crypto
            // stream that you are through using it, and thus to finish processing any
            // bytes remaining in the buffer used by the crypto stream. Typically this
            // involves padding the last output block to a complete multiple of the crypto
            // object's block size (for Rijndael this is 16 bytes, or 128 bits),
            // encrypting it, and then writing this final block to the memory stream.
            csEncrypted.FlushFinalBlock();

            // Clean up. There is no need to call fsCipherText.Close() because closing the
            // crypto stream automatically encloses the stream that was passed into it.
            csEncrypted.Close();
            return Convert.ToBase64String(stmCipherText.ToArray());
            //SwapFiles(False)
        }

        // This routine opens the .dat file, reads in the salt and IV, and then
        // sets the crypto object's key and IV.
        private void OpenSaltIVFileAndSetKeyIV()
        {

            // Initialize the byte arrays to the proper length for the
            // instantiated crypto class.
            ReDimByteArrays();

            // Create a Filestream object to read in the contents of the .dat file
            // that contains the salt and IV.
            FileStream fsKey = new FileStream(strSaltIVFile, FileMode.Open, FileAccess.Read);
            fsKey.Read(abytSalt, 0, abytSalt.Length);
            fsKey.Read(abytIV, 0, abytIV.Length);
            fsKey.Close();

            // Derive the key from the salted password.
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(strPassword, abytSalt);
            // Get the same amount of bytes as the current abytKey length as set in
            // ReDimByteArrays().
            abytKey = pdb.GetBytes(abytKey.Length);


            // Assign the byte arrays to the Key and IV properties of the instantiated
            // symmetric crypto class.
            crpSym.Key = abytKey;
            crpSym.IV = abytIV;

        }

        // This routine redimensions the byte arrays to the proper length for the
        // instantiated crypto class.
        private void ReDimByteArrays()
        {

            if (crpSym.GetType() == typeof(System.Security.Cryptography.RijndaelManaged))
            {
                
                abytKey = new byte[32];
                
                abytSalt = new byte[16];
                
                abytIV = new byte[16];
            }
            else
            {
                abytKey = new byte[24];
                abytSalt = new byte[12];
                abytIV = new byte[8];
            }
        }


        public string Mahoa(string chuoi)
        {
            try
            {
                Encrypt crpSample = new Encrypt("Rijndael");
                string pPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).ToString();
                pPath = pPath.Substring(6);
                crpSample.SaltIVFile = pPath + "\\data.dat";
                crpSample.Password = "cmis2004";
                return crpSample.EncryptString(chuoi, Password).Replace("\'", "0");
            }
            catch (Exception expCrypto)
            {
                return expCrypto.Message;
            }
        }
        public string GiaiMa(string chuoi)
        {
            try
            {
                Encrypt crpSample = new Encrypt("Rijndael");
                string pPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).ToString();
                pPath = pPath.Substring(6);
                crpSample.SaltIVFile = pPath + "\\data.dat";
                crpSample.Password = "cmis2004";

                return crpSample.DecryptString(chuoi, Password).Replace("\'", "0");
            }
            catch (Exception expCrypto)
            {
                return expCrypto.Message;
            }
            
        }

        public static string GiaiMastatic(string chuoi)
        {
            try
            {
                Encrypt crpSample = new Encrypt("Rijndael");
                string pPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).ToString();
                pPath = pPath.Substring(6);
                crpSample.SaltIVFile = pPath + "\\data.dat";
                crpSample.Password = "cmis2004";

                return crpSample.DecryptString(chuoi, "cmis2004").Replace("\'", "0");
            }
            catch (Exception expCrypto)
            {
                return expCrypto.Message;
            }

        }
    }
}
